<script setup>
import { ref, onMounted } from 'vue'
import { customTranslate } from './translate/translatation';
import { xmlStr } from './translate/xmlStr';
import FlowableModdle from './flowable/flowable.json'
import { CustomModeler } from './customModeler'
import 'bpmn-js/dist/assets/diagram-js.css'
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css'
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css'
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css'

import { NodeName } from './translate/zh';
import ProcessPanel from './components/ProcessPanel.vue'
import StartEndPanel from './components/StartEndPanel.vue'
import GatewayPanel from './components/GatewayPanel.vue'
import SequenceFlowPanel from './components/SequenceFlowPanel.vue'
import TaskPanel from './components/TaskPanel.vue'

// import lintModule from 'bpmn-js-bpmnlint'
// import 'bpmn-js-bpmnlint/dist/assets/css/bpmn-js-bpmnlint.css'
// import bpmnlintConfig from './.bpmnlintrc'

const bpmnModeler = ref()
const canvasRef = ref()
const element = ref()
const type = ref({
  name: '',
  type: '',
})
// const props = defineProps({
//   customForm: Object
// })
const customXml = defineModel("customXml", {
  type: String,
  default: ""
})
const isComponentShow = ref(true)
async function createNewDiagram(bpmn) {
  try {
    const result = await bpmnModeler.value.importXML(bpmn)
    const { warnings } = result
    console.log(warnings)
    success()
    // renameInit()
  } catch (e) {
    console.log('error-->', e)
  }
}

// 监听点击事件，输出事件信息（包括元素信息）
function success() {
  const eventBus = bpmnModeler.value.get("eventBus")
  eventBus.on("element.click", function (e) {
    // console.log('element', e.element)
    // console.log("elementBusinessObject", e.element.businessObject)
    element.value = e.element.businessObject
    type.value.type = e.element.businessObject.$type
    type.value.name = NodeName[e.element.businessObject.$type]
    isComponentShow.value = true
  })
  // 创建元素时
  eventBus.on("shape.added", function (e) {
    console.log('element.added')
    element.value = e.element.businessObject
    type.value.type = e.element.businessObject.$type
    type.value.name = NodeName[e.element.businessObject.$type]
    isComponentShow.value = true
  })
  // 同步xml至父组件
  eventBus.on('elements.changed', async function () {
    const { xml } = await bpmnModeler.value.saveXML({ format: true })
    customXml.value = xml

  })
  // 删除元素时
  eventBus.on("shape.removed", function (e) {
    console.log('shape.removed', e.element)
    isComponentShow.value = false

  })

}

// function renameInit() {
//   const modeling = bpmnModeler.value.get("modeling")
//   modeling.updateProperties(bpmnModeler.value.get("elementRegistry").getAll()[0], { name: '流程' })
// }
// 导入xml
const init = () => {
  const customTranslateModule = {
    translate: ['value', customTranslate]
  }
  bpmnModeler.value = new CustomModeler({
    container: canvasRef.value,
    propertiesPanel: {
      parent: '#js-properties-panel'
    },
    keyboard: {
      bindTo: window
    },
    // linting: {
    //   active: true,
    //   bpmnlint: bpmnlintConfig
    // },
    additionalModules: [
      customTranslateModule,
      // lintModule
    ],
    moddleExtensions: {
      flowable: FlowableModdle,
    }
  })
  if (customXml.value) {
    createNewDiagram(customXml.value)
  } else {
    createNewDiagram(xmlStr)
  }
}
onMounted(() => {
  init()

})

const newXml = ref('')
async function showxml() {
  console.log(bpmnModeler.value)
  const { xml } = await bpmnModeler.value.saveXML({ format: true })
  isShowXML.value = true
  // newXml.value = xml.replaceAll('bpmn2:', '')
  newXml.value = xml
}

function handlerUndo() {
  bpmnModeler.value.get('commandStack').undo()
}
function handlerRedo() {
  bpmnModeler.value.get('commandStack').redo()
}
function componentActive() {
  if (['bpmn:IntermediateThrowEvent', 'bpmn:StartEvent', 'bpmn:EndEvent'].includes(type.value.type)) {
    return StartEndPanel
  }
  if ([
    'bpmn:UserTask',
    'bpmn:Task',
    'bpmn:SendTask',
    'bpmn:ReceiveTask',
    'bpmn:ManualTask',
    'bpmn:BusinessRuleTask',
    'bpmn:ServiceTask',
    'bpmn:ScriptTask'
    // 'bpmn:CallActivity',
    // 'bpmn:SubProcess'
  ].includes(type.value.type)) {
    return TaskPanel
  }
  if (type.value.type === 'bpmn:SequenceFlow') {
    return SequenceFlowPanel
  }
  if ([
    'bpmn:InclusiveGateway',
    'bpmn:ExclusiveGateway',
    'bpmn:ParallelGateway',
    'bpmn:EventBasedGateway'
  ].includes(type.value.type)) {
    return GatewayPanel
  }
  if (type.value.type === 'bpmn:Process') {
    return ProcessPanel
  }
  return null
}

const fold = ref(false)
// const unfold = ref(true)
const isShowXML = ref(false)
// TODO 集成时命名为process的name

// API相关
import { saveXml } from '@/api/flowable/defination'
async function handleSaveXml() {
  console.log(newXml.value)
  const { xml } = await bpmnModeler.value.saveXML({ format: true })
  await saveXml({
    name: '测试流程',
    category: 'equipment',
    xml: xml,
  })
    .then((res) => {
      console.log(res)
    })
}

</script>
<template>

  <div class="process">
    <div class="toolbar">
      <el-button @click="showxml" plain type="primary">导出</el-button>
      <el-button @click="handlerUndo" plain type="primary">撤销</el-button>
      <el-button @click="handlerRedo" plain type="primary">恢复</el-button>
      <el-button @click="showxml" plain type="primary">预览</el-button>
      <el-button @click="handleSaveXml" plain type="primary">上传</el-button>
    </div>
    <div class="containers">
      <div class="canvas" ref="canvasRef">
      </div>
      <div class="panel" :class="{ fold: fold }">
        <div class="content" v-if="!fold && isComponentShow">
          <el-text v-if="type" size="large" tag="b">{{ type.name }}</el-text>
          <el-divider></el-divider>
          <component :is="componentActive()" v-model:element="element" :bpmnModeler="bpmnModeler" />
        </div>
        <el-icon class="unfold" @click="fold = true" v-show="!fold">
          <DArrowRight />
        </el-icon>
        <el-icon class="fold" @click="fold = false" v-show="fold">
          <DArrowLeft />
        </el-icon>
      </div>
    </div>
  </div>
  <el-dialog title="" v-model="isShowXML" width="800">
    <el-scrollbar>
      <!-- <pre v-highlight="newXml"><code class="xml"></code></pre> -->
      <highlightjs language='javascript' :code="newXml" />
    </el-scrollbar>
  </el-dialog>
</template>

<style scoped lang="less">
.process {
  position: relative;
  display: flex;
  width: 100%;
  height: 100%;

  .toolbar {
    position: absolute;
    top: 10px;
    left: 10px;
  }

  .containers {
    // 以下constainers的css为流程图背景
    background: white;
    overflow: hidden;
    background-image: linear-gradient(90deg,
        rgba(220, 220, 220, 0.5) 6%,
        transparent 0),
      linear-gradient(rgba(192, 192, 192, 0.5) 6%, transparent 0);
    background-size: 12px 12px;
    width: 100%;
    height: calc(100vh - 60px);
    -webkit-tap-highlight-color: rgba(255, 255, 255, 0);

    .canvas {
      // overflow: hidden;
      // flex-direction: row-reverse;
      margin-top: 40px;
      width: 100%;
      // width: 100%;
      height: 100%;
    }

  }

  .panel {
    position: absolute;
    right: 0;
    top: 10px;
    width: 600px;
    height: calc(100%);
    box-sizing: border-box;
    background-color: #fff;
    border-style: solid;
    border-radius: 10px 0 0 10px;
    border-right: none;
    border-color: var(--el-color-info);
    z-index: 300;
    // overflow-y: scroll;
    // overflow-x: inherit;

    .content {
      margin: 30px 10px 0 20px;
      overflow-y: scroll;
      overflow-x: hidden;

      .el-divider {
        margin: 10px 0;
      }
    }

    .fold,
    .unfold {
      position: absolute;
      height: 100px;
      width: 20px;
      left: -24px;
      top: 50%;
      transform: translateY(-50%);
      border: 2px solid var(--el-color-info);
      border-right: none;
      border-radius: 8px 0 0 4px;
      background-color: var(--el-color-success);


      &:hover {
        cursor: pointer;
      }
    }
  }

  .panel.fold {
    transition: all 0.3s;
    width: 10px;
    background-color: var(--el-color-success-light-8);
  }

  .panel {
    translate: 0px;
  }
}

.el-form {
  margin-top: 10px;
}
</style>
